Skip to content

Wait for data before async recv#94

Open
vojtech-frodl wants to merge 1 commit intojonasmr:masterfrom
vojtech-frodl:fix-nonblocking-read
Open

Wait for data before async recv#94
vojtech-frodl wants to merge 1 commit intojonasmr:masterfrom
vojtech-frodl:fix-nonblocking-read

Conversation

@vojtech-frodl
Copy link

This fixes an issue where recv() is called on a non-blocking socket immediately after accept() before it's ready for reading, returns -1 and the connection is closed.

I found this when I was trying to profile a Windows executable running in Wine on Linux in a Docker container in Kubernetes on AWS. I tried to connect to it from a local web browser via kubectl port-forward and it kept closing the connection 100% of the times. This was the only setup I was able to reproduce it with. I believe the kubectl port-forward was the main trigger for the issue because I didn't observe it when connecting from inside the Docker container.

@jonasmr
Copy link
Owner

jonasmr commented Dec 17, 2025

Hi! Thank you for your submit.

So to understand it correctly, you're saying that you have to call select between the accept and the recv?
To me it looks like the recv is actually supposed to be blocking, but its been a while since I've looked at this.

@vojtech-frodl
Copy link
Author

Hi, yes, that's what I observed, select between accept and recv fixed it. If the socket was intended to be blocking, it wasn't in my case, as far as I could tell.

@vojtech-frodl
Copy link
Author

Then again, MicroProfileSetNonBlocking(S.ListenerSocket, 1); is being called, so maybe it's supposed to be non-blocking after all?

@jonasmr
Copy link
Owner

jonasmr commented Dec 17, 2025

I think this is where it is platform dependent. I'm pretty sure I remember window always creates sockets in Blocking mode.

@vojtech-frodl
Copy link
Author

This is my understanding as well:
https://learn.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls#fionbio

When a socket is created, it operates in blocking mode (that is, non-blocking mode is disabled).

The ListenerSocket is created as non-blocking here:

S.ListenerSocket = socket(PF_INET, SOCK_STREAM, 6);
MP_ASSERT(!MP_INVALID_SOCKET(S.ListenerSocket));
MicroProfileSetNonBlocking(S.ListenerSocket, 1);

Then MpSocket Connection = accept(S.ListenerSocket, 0, 0); creates a new socket Connection which is also non-blocking:
https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-accept#remarks

The newly created socket is the socket that will handle the actual connection; it has the same properties as socket s

@jonasmr
Copy link
Owner

jonasmr commented Dec 18, 2025

Hi.

Can you try this code, and see if this fixes your issue?

The intent of the code here is that the socket should be blocking, but it seems like it isn't.
These changes should fix it up, and hopefully let you continue

diff --git a/microprofile.cpp b/microprofile.cpp
index b5a86cc..f37ea13 100644
--- a/microprofile.cpp
+++ b/microprofile.cpp
@@ -8411,6 +8411,7 @@ bool MicroProfileWebServerUpdate()
 	if(!MP_INVALID_SOCKET(Connection))
 	{
 		std::lock_guard<std::recursive_mutex> Lock(MicroProfileMutex());
+		MicroProfileSetNonBlocking(Connection, 0);
 		char Req[8192];
 		int nReceived = recv(Connection, Req, sizeof(Req) - 1, 0);
 		if(nReceived > 0)
@@ -8470,7 +8471,7 @@ bool MicroProfileWebServerUpdate()
 				{
 				case EMICROPROFILE_GET_COMMAND_LIVE:
 				{
-					MicroProfileSetNonBlocking(Connection, 0);
+					//MicroProfileSetNonBlocking(Connection, 0);
 					uint64_t nTickStart = MP_TICK();
 					send(Connection, MICROPROFILE_HTML_HEADER, sizeof(MICROPROFILE_HTML_HEADER) - 1, 0);
 					uint64_t nDataStart = S.nWebServerDataSent;
@@ -8509,7 +8510,7 @@ bool MicroProfileWebServerUpdate()
 				case EMICROPROFILE_GET_COMMAND_DUMP:
 				{
 					{
-						MicroProfileSetNonBlocking(Connection, 0);
+						//MicroProfileSetNonBlocking(Connection, 0);
 						uint64_t nTickStart = MP_TICK();
 						send(Connection, MICROPROFILE_HTML_HEADER, sizeof(MICROPROFILE_HTML_HEADER) - 1, 0);
 						uint64_t nDataStart = S.nWebServerDataSent;

@vojtech-frodl
Copy link
Author

Confirming that your fix also works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants